package com.zeng.createmd.restfulmodule.util;

import com.zeng.createmd.restfulmodule.constant.DataSaveLocation;
import com.zeng.createmd.restfulmodule.itemCache.ItemCache;
import com.zeng.plugin.entity.MenuView;
import com.zeng.plugin.entity.TableEntity;
import com.zeng.plugin.entity.TableRelative;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

public class ProjectUtil {

    private String path;

    private Map<String, Object> data;

    public String getPath() {
        return this.path;
    }

    public Map<String, Object> getData() {
        return this.data;
    }

    public ProjectUtil(String path) {
        this.path = path;
        this.data = SerializableUtil.deserialize(new File(path));
        if (this.data != null) {
            return;
        }
        this.data = new HashMap<>();
    }

    public ProjectUtil() {
        this(new File(ItemCache.currentItem.getPath(), "data.z").getAbsolutePath());
    }

    public void init() {
        SerializableUtil.serialize(new File(this.path), this.data);
    }

    public Object getTable(String realTableName) {
        Object tables = this.getData().get("tables");
        TableEntity tableEntity = ((List<TableEntity>) tables).stream().filter(e -> {
            return e.getRealTableName().equals(realTableName);
        }).findFirst().orElse(null);
        return tableEntity;
    }

    public void removeTable(String realTableName) {
        Object table = this.getTable(realTableName);
        if (table != null) {
            this.removeTableMap(realTableName);
            ((List<TableEntity>) (this.getData().get("tables"))).remove(table);
            this.init();
        }
    }

    public Object getTableMap(String tableName) {
        Object tableMap = this.getData().get("tableMap");

        if (tableMap == null) {
            return null;
        }
        return ((Map<String, Object>) tableMap).get(tableName);
    }

    public void putTableMap(String tableName, Object value) {
        Object tableMap = this.getData().get("tableMap");
        if (tableMap == null) {
            HashMap<String, Object> tableMapTamplate = new HashMap<>();
            this.getData().put("tableMap", tableMapTamplate);
            tableMap = tableMapTamplate;
        }
        ((Map<String, Object>) tableMap).put(tableName, value);

    }

    public void removeTableMap(String tableName) {
        Optional<Map<String, Object>> tableMap = Optional.ofNullable(((Map<String, Object>) this.getData().get("tableMap")));
        tableMap.ifPresent((e) -> e.remove(tableName));
    }

    public Map<String, TableRelative> getTableRelativeByTableName(String tableName) {
        Map<String, Map<String, TableRelative>> tableRelative = (Map<String, Map<String, TableRelative>>) this.getData().get("tableRelative");
        if (tableRelative == null) {
            return null;
        }
        return tableRelative.get(tableName);
    }

    public Map<String, Map<String, TableRelative>> getTableRelative() {
        Map<String, Map<String, TableRelative>> tableRelative = (Map<String, Map<String, TableRelative>>) this.getData().get("tableRelative");
        if (tableRelative == null) {
            tableRelative = new HashMap<>();
            this.getData().put("tableRelative", tableRelative);
            init();
        }
        return tableRelative;
    }

    public void putTableRelative(String tableName, Map<String, TableRelative> relativeMap) {
        Map<String, Map<String, TableRelative>> tableRelative = (Map<String, Map<String, TableRelative>>) this.getData().get("tableRelative");

        if (tableRelative == null) {
            HashMap<String, Map<String, TableRelative>> stringMapHashMap = new HashMap<>();
            this.getData().put("tableRelative", stringMapHashMap);
            tableRelative = stringMapHashMap;
        }
        tableRelative.put(tableName, relativeMap);
        this.init();
    }

    public void removeTableRelativeValue(TableRelative relative) {
        if (relative == null) {
            return;
        }
        Optional.ofNullable(((Map<String, Map<String, TableRelative>>) getTableRelative()))
                .ifPresent(e -> {
                    Map<String, TableRelative> stringTableRelativeMap = e.get(relative.getTable1());
                    if (stringTableRelativeMap != null) {
                        stringTableRelativeMap.remove(relative.getTable2());
                    }

                    Map<String, TableRelative> stringTableRelativeMap1 = e.get(relative.getTable2());
                    if (stringTableRelativeMap1 != null) {
                        stringTableRelativeMap1.remove(relative.getTable1());
                    }
                });
        removeRelativeList(relative);
        init();

    }

    public void createTableRelative(TableRelative tableRelative) {
        Map<String, Map<String, TableRelative>> relative = getTableRelative();

        Map<String, TableRelative> table1 = relative.get(tableRelative.getTable1());
        if (table1 == null) {
            HashMap<String, TableRelative> value = new HashMap<>();
            table1 = value;
            relative.put(tableRelative.getTable1(), value);
        }
        table1.put(tableRelative.getTable2(), tableRelative);

        Map<String, TableRelative> table2 = relative.get(tableRelative.getTable2());
        if (table2 == null) {
            HashMap<String, TableRelative> value = new HashMap<>();
            table2 = value;
            relative.put(tableRelative.getTable2(), value);
        }
        table2.put(tableRelative.getTable1(), tableRelative);

        addRelativeList(tableRelative);
        init();
    }

    public List<TableRelative> relativeList() {
        Object relativeList = this.getData().get("relativeList");
        if (relativeList == null) {
            ArrayList<TableRelative> tableRelatives = new ArrayList<>();
            this.getData().put("relativeList", tableRelatives);
            return tableRelatives;
        }
        return (List<TableRelative>) relativeList;
    }

    public void addRelativeList(TableRelative tableRelative) {
        removeRelativeList(tableRelative);
        List<TableRelative> tableRelatives = relativeList();
        tableRelatives.add(tableRelative);
        init();
    }

    public void removeRelativeList(TableRelative tableRelative) {
        List<TableRelative> tableRelatives = relativeList();
        tableRelatives.stream()
                .filter(e -> e.getTable1().equals(tableRelative.getTable1()) && tableRelative.getTable2().equals(e.getTable2()))
                .collect(Collectors.toList())
                .forEach(e -> tableRelatives.remove(e));
        tableRelatives.stream()
                .filter(e -> e.getTable2().equals(tableRelative.getTable1()) && tableRelative.getTable2().equals(e.getTable1()))
                .collect(Collectors.toList())
                .forEach(e -> tableRelatives.remove(e));
        init();
    }

    public Map<String, MenuView> getMenuViews() {
        Map<String, MenuView> menuView = (Map<String, MenuView>) getData().get("menuView");
        if (menuView == null) {
            menuView = new HashMap<>();
            getData().put("menuView", menuView);
            init();
        }
        return menuView;
    }

    public void putMenuView(MenuView menuView) {
        if (menuView == null || StringUtils.isEmpty(menuView.getTableName())) {
            throw new RuntimeException("menuView不能为空或者是表名不能为空");
        }
        getMenuViews().put(menuView.getTableName(), menuView);
        init();
    }

    public void removeMenuView(String tableName) {
        if (StringUtils.isEmpty(tableName)) {
            throw new RuntimeException("表名不能为空");
        }
        getMenuViews().remove(tableName);
        init();
    }

}

